﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq.Mapping;
using System.Reflection;
using System.Globalization;

using LeanEngine.Reflection;

namespace LeanEngine.Entity
{
    public struct MetaColumn
    {
        #region Constructor Members

        public MetaColumn(PropertyInfo property)
            : this()
        {
            PropertyInfo = property;
            DBColumn = property.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault() as ColumnAttribute;
            
            GetValue = (entity) => property.FastGetValue(entity);
            SetValue = (entity, value) => property.FastSetValue(entity, value);
            SaveStateInvoker = (instance) =>
                {
                    var method = property.PropertyType.GetMethod("SaveState");
                    if (method != null)
                    {
                        method.FastInvoke(instance, null);
                    }
                };
        }

        #endregion

        #region Property Members
        
        public string PropertyName { get { return this.PropertyInfo == null ? string.Empty : this.PropertyInfo.Name; } }
        public bool IsEntity { get { return this.PropertyInfo == null ? false : this.PropertyInfo.PropertyType.IsSubclassOf(typeof(Entity.PlainEntity)); } }
        public bool IsEnum { get { return this.PropertyInfo == null ? false : this.PropertyInfo.PropertyType.IsEnum; } }
        public bool IsGuid { get { return this.PropertyInfo == null ? false : this.PropertyInfo.PropertyType == typeof(Guid); } }
        public Type DataType { get { return this.PropertyInfo == null ? null : this.PropertyInfo.PropertyType; } }

        public PropertyInfo PropertyInfo { get; set; }
        public ColumnAttribute DBColumn { get; private set; }

        public Action<object> SaveStateInvoker { get; private set; }
        public Action<object, object> SetValue { get; private set; }
        public Func<object, object> GetValue { get; private set; }

        #endregion

        #region Method Members

        public object NewEntityInstance()
        {
            return this.PropertyInfo.PropertyType.FastCreateInstance(null);
        }

        public object ChangeType(object value)
        {
            return Convert.ChangeType(value, PropertyInfo.PropertyType, CultureInfo.CurrentCulture);
        }

        #endregion
    }
}
